﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Reflection;
using Managistics.Core.Infrastructure;
using Managistics.Core.Repositories;
using Managistics.Core.Services;
using Managistics.Model;
using OfficeOpenXml;

namespace Managistics.Core.Services.Impl
{
    public class InventoryService : IInventoryService
    {
        const string DELIMITER = "\t\t | \t\t";

        private readonly IGoodRepository _goodRepository;

        public InventoryService(IGoodRepository goodRepository)
        {
            _goodRepository = goodRepository;
        }

        [UnitOfWork]
        public int ImportToCreateRelations(string filePath, int startRow)
        {
            // Old good records
            GoodDataRecord oldRecord = null;
            GoodDataRecord currentRecord = null;
            int currentRowNumber = 0;
            filePath = "D:\\SimpleListRelations.xlsx";
            try
            {
                if (File.Exists(filePath))
                {
                    IList<GoodDataRecord> goodDataList = new List<GoodDataRecord>();

                    // Get the file we are going to process
                    var existingFile = new FileInfo(filePath); 
                    // Open and read the XlSX file.
                    using (var package = new ExcelPackage(existingFile))
                    {
                        // Get the work book in the file
                        ExcelWorkbook workBook = package.Workbook;
                        if (workBook != null)
                        {
                            if (workBook.Worksheets.Count > 0)
                            {
                                // Get the first worksheet
                                ExcelWorksheet currentWorksheet = workBook.Worksheets.First();

                                for (int rowNumber = startRow; rowNumber <= currentWorksheet.Dimension.End.Row; rowNumber++)
                                // read each row from the start of the data (start row + 1 header row) to the end of the spreadsheet.
                                {
                                    currentRowNumber = rowNumber;
                                    object goodCodeValue = currentWorksheet.Cells[rowNumber, 1].Value;
                                    object unitNameValue = currentWorksheet.Cells[rowNumber, 4].Value;
                                    // xx: Retail code, huong: Parity code
                                    object relationValue = currentWorksheet.Cells[rowNumber, 5].Value;

                                    if (goodCodeValue == null)
                                    {
                                        break;
                                    }

                                    string unitName = string.Empty;
                                    int convertUnit = 0;

                                    // set values for current record
                                    currentRecord = new GoodDataRecord()
                                    {
                                        GoodCode = goodCodeValue.ToString().PadLeft(6, '0'),
                                        UnitName = unitNameValue.ToString(),
                                        // xx or hương
                                        Relation = (relationValue != null ? relationValue.ToString() : string.Empty)
                                    };

                                    // if not set relation, blank
                                    if (string.IsNullOrEmpty(currentRecord.Relation))
                                    {
                                        oldRecord = null;
                                    }
                                    else if (currentRecord.Relation.Equals("hương"))
                                    {
                                        // remove any characters, only get 4 first characters
                                        int limit = (currentRecord.UnitName.Length >= 4 ? 3 : currentRecord.UnitName.Length - 1);
                                        int check = 0;

                                        unitName = Regex.Replace(currentRecord.UnitName.Substring(0, limit), @"[^0-9]", string.Empty);
                                        if (!String.IsNullOrEmpty(unitName) && int.TryParse(unitName, out convertUnit))
                                        {
                                            currentRecord.ConvertUnit = convertUnit;
                                        }
                                        else
                                        {
                                            //Console.WriteLine(String.Format(rowNumber + "{0}" + currentRecord + "{0}" + "unit not valid", DELIMITER));
                                            check++;
                                        }

                                        // check the old good not xx: Retail code
                                        if (oldRecord == null || (oldRecord != null && !oldRecord.Relation.ToLower().Equals("xx")))
                                        {
                                            //Console.WriteLine(String.Format(rowNumber + "{0}" + currentRecord + "{0}" + "Parity code not valid", DELIMITER));
                                            check++;
                                        }

                                        // check to save object to database
                                        if (check == 2)
                                        {
                                            Console.WriteLine("unit not valid && parity code not valid");
                                        }
                                        else if (check == 0 && oldRecord.Relation.ToLower().Equals("xx"))
                                        {
                                            // ma chan
                                            Good ParityGood = _goodRepository.GetGoodById(currentRecord.GoodCode);
                                            // ma le
                                            Good RetailGood = _goodRepository.GetGoodById(oldRecord.GoodCode);

                                            // save to database
                                            if (ParityGood != null && RetailGood != null)
                                            {
                                                // update by repository
                                                RetailGood.Paritycode = ParityGood.Code;
                                                RetailGood.Convertunit = currentRecord.ConvertUnit;

                                                _goodRepository.Update(RetailGood);

                                                Console.WriteLine("---------updated good--------");
                                                Console.WriteLine(String.Format(rowNumber + "{0}" + RetailGood.Code + "{0}", DELIMITER));
                                            }
                                            else
                                            {
                                                Console.WriteLine("---------good not found--------");
                                                if (ParityGood == null)
                                                {
                                                    Console.WriteLine(String.Format(rowNumber + "{0}" + ParityGood.Code + "{0}" + "not found", DELIMITER));
                                                }
                                                if (RetailGood == null)
                                                {
                                                    Console.WriteLine(String.Format(rowNumber + "{0}" + RetailGood.Code + "{0}" + "not found", DELIMITER));
                                                }
                                            }
                                        }
                                    }
                                    else
                                    {
                                        oldRecord = currentRecord;
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {

                }
            }
            catch (IOException ioEx)
            {
                if (!String.IsNullOrEmpty(ioEx.Message))
                {
                    if (ioEx.Message.Contains("because it is being used by another process."))
                    {
                        Console.WriteLine("Could not read example data. Please make sure it not open in Excel.");
                    }
                }
                Console.WriteLine("Could not read example data. " + ioEx.Message, ioEx);
            }
            catch (Exception ex)
            {
                Console.WriteLine("An error occured while reading example data. " + ex.Message, ex);
                Console.WriteLine(String.Format(currentRowNumber + "{0}" + currentRecord + "{0}" + "error", DELIMITER));
            }
            finally
            {
                Console.WriteLine("finished.");
            }
            return 0;
        }

        public static string GetDelimiter()
        {
            return DELIMITER;
        }
    }

    class GoodDataRecord
    {
        public string GoodCode { get; set; }
        public string UnitName { get; set; }
        public string Relation { get; set; }
        public int ConvertUnit { get; set; }

        public override string ToString()
        {
            return String.Format(GoodCode + "{0}" + UnitName + "{0}" + Relation + "{0}"  + ConvertUnit, InventoryService.GetDelimiter());
        }
    }
}